﻿/*
 * Copyright 2021 KylinSoft Co., Ltd.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "powermanagercenter.h"
#include "config.h"
#include "brightness.h"
#include "idle.h"
#include "lid.h"
#include "lowbattery.h"
#include "powermanagercontrol.h"
#include "notification.h"
#include "batterysaving.h"
#include "compatibleinterface.h"

PowerManagerCenter::PowerManagerCenter() : m_config(Singleton<Config>::Instance())
{
    qDebug() << "init power manager center";
    initPowerManagerCenter();
}

PowerManagerCenter::~PowerManagerCenter() {}

void PowerManagerCenter::initPowerManagerCenter()
{
    //初始化顺序不要轻易改动
    int machineType = m_config->machineType();
    qDebug() << "init power modult";
    initPowerModule(machineType);
    qDebug() << "init power connect";
    initPowerConnect(machineType);
    qDebug() << "init power data";
    initPowerData(machineType);
}

void PowerManagerCenter::initPowerModule(const int &type)
{
    m_idle = Singleton<Idle>::Instance();
    m_compatibleInterface = Singleton<CompatibleInterface>::Instance();
    m_control = Singleton<PowerManagerControl>::Instance();
    if (Laptop == type) {
        m_notification = Singleton<Notification>::Instance();
        m_batterySaving = Singleton<BatterySaving>::Instance();
        m_brightness = Singleton<Brightness>::Instance();
        m_lid = Singleton<Lid>::Instance();
        m_lowBattery = Singleton<LowBattery>::Instance();
    }
    qDebug() << "init power modult success";
}

void PowerManagerCenter::initPowerConnect(const int &type)
{
    qDebug() << "connect Init";
    connect(m_config, &Config::configChanged, this, [=](QStringList list) { dealConfigEvent(list); });
    connect(m_idle, &Idle::idleChanged, this, [=](QString type) { dealIdleEvent(type); });
    connect(m_idle, &Idle::suspendTimeout, this, [=](QString type) { dealIdleEvent(type); });
    connect(m_idle, &Idle::turnOffDisplayTimeout, this, [=](QString type) { dealIdleEvent(type); });
    if (Laptop == type) {
        bool result = QDBusConnection::sessionBus().connect(
            UKUI_UPOWER_SERVICE,
            UKUI_UPOWER_PATH,
            UKUI_UPOWER_INTERFACE,
            "PowerState",
            this,
            SLOT(dealPowerStateChanged(bool)));
        if (!result) {
            qCritical() << "error code: " << POWER_STATE_CREATE_CONNECTION_ERROR;
        }
        result = QDBusConnection::sessionBus().connect(
            UKUI_UPOWER_SERVICE,
            UKUI_UPOWER_BATTERY_PATH,
            UKUI_UPOWER_BATTERY_INTERFACE,
            "BatteryState",
            this,
            SLOT(dealBatteryStateChanged(int)));
        if (!result) {
            qCritical() << "error code: " << BATTERY_STATE_CREATE_CONNECTION_ERROR;
        }
        connect(m_idle, &Idle::reduceBrightnessTimeout, this, [=](QString type) { dealIdleEvent(type); });
        connect(m_lid, &Lid::lidChanged, this, [=](bool state) { dealLidChanged(state); });
        connect(m_lowBattery, &LowBattery::veryLowBatteryTimeout, this, [=]() { dealLowBatteryControl(); });
        connect(
            m_lowBattery, &LowBattery::lowBatteryStateChanged, this, [=](int state) { dealLowBatteryChanged(state); });
        m_batterySaving->initConnect();
    }
}

void PowerManagerCenter::initPowerData(const int &type)
{
    if (Laptop == type) {
        m_onBattery = getOnBatteryState();
        m_brightness->setBrightness(m_config->getSysData().sysBrightness);
        qDebug() << "init on battery:" << m_onBattery;
        if (m_onBattery) {
            m_control->dealControlAction(POWER_POLICY_BATTERY, m_config->getSysData().sysPowerPolicyBat);
            dealLowBatteryChanged(m_lowBattery->getLowBatteryWarning());
            m_batterySaving->setBatterySaver(batterySaverOff);
        } else {
            m_batterySaving->setBatterySaver(batterySaverUnavailable);
        }
        m_batterySaving->initBatterySavingState();
    }
    m_control->dealControlAction(POWER_POLICY_AC, m_config->getSysData().sysPowerPolicyAc);
    setIdleTime(type);
}

void PowerManagerCenter::dealLidChanged(const bool &state)
{
    QString action;
    qDebug() << "deal lid changed! lid state " << state;
    if (m_onBattery) {
        action = transformData(m_config->getSysData().sysButtonLidBat);
    } else {
        action = transformData(m_config->getSysData().sysButtonLidAc);
    }
    if (state) {
        qDebug() << "lid changed will action" << action;
        m_control->dealControlAction(action, true);
    } else {
        if (TURN_OFF_DISPLAY == action) {
            m_control->dealControlAction(TURN_ON_DISPLAY, true);
        }
    }
}

void PowerManagerCenter::dealIdleEvent(const QString &type)
{
    int machineType = m_config->machineType();
    qDebug() << "deal idle event! event type :" << type;
    if (SLEEP_COMPUTER == type) {
        m_control->dealControlAction(SUSPEND, true);
    } else if (SLEEP_DISPLAY == type) {
        m_control->dealControlAction(TURN_OFF_DISPLAY, true);
    } else if (REDUCE_BRIGHTNESS == type) {
        m_brightness->reduceBrightness();
        m_isIdleBrightness = true;
    } else if (ENTER_IDLE_STATE == type) {
        setIdleTime(machineType);
    } else if (EXIT_IDLE_STATE == type) {
        if (Laptop == machineType && m_isIdleBrightness) {
            m_brightness->restoreBrightness();
            m_isIdleBrightness = false;
        }
    }
}

void PowerManagerCenter::dealConfigEvent(const QStringList &changedList)
{
    qDebug() << "config changed list id :" << changedList;
    QString changeKey;
    for (int var = 0; var < changedList.size(); ++var) {
        changeKey = changedList.at(var);
        dealSysDateChanged(changeKey);
    }
}

void PowerManagerCenter::dealSysDateChanged(const QString &type)
{
    qDebug() << "change key :" << type;
    if (Laptop == m_config->machineType()) {
        if (BRIGHTNESS == type) {
            m_brightness->setBrightness(m_config->getSysData().sysBrightness);
        } else if (POWER_POLICY_BATTERY == type && m_onBattery) {
            m_control->dealControlAction(POWER_POLICY_BATTERY, m_config->getSysData().sysPowerPolicyBat);
        } else if (BATTERY_SAVER) {
            m_batterySaving->dealBatterySaver(m_config->getSysData().sysBatterySaver);
        } else if (BATTERY_SAVER_BRIGHTNESS) {
            m_batterySaving->setBatterySaverBrightness(m_config->getSysData().sysBatterySaverBrightness);
        } else if (ACTION_CRITICAL_BATTERY) {
            m_lowBattery->setDialogMsg();
        }
    }
    if (POWER_POLICY_AC == type) {
        m_control->dealControlAction(POWER_POLICY_AC, m_config->getSysData().sysPowerPolicyAc);
    }
}

void PowerManagerCenter::dealPowerStateChanged(bool state)
{
    qDebug() << "m_onBattery " << m_onBattery << "changed state :" << state;
    if (m_onBattery != state) {
        m_onBattery = state;
        if (m_onBattery) {
            m_control->dealControlAction(POWER_POLICY_BATTERY, m_config->getSysData().sysPowerPolicyBat);
            if (batterySaverUnavailable == m_config->getSysData().sysBatterySaver) {
                m_batterySaving->setBatterySaver(batterySaverOff);
            }
        } else {
            m_control->dealControlAction(POWER_POLICY_AC, m_config->getSysData().sysPowerPolicyAc);
            m_batterySaving->setBatterySaver(batterySaverUnavailable);
        }
    }
}

void PowerManagerCenter::dealBatteryStateChanged(int state)
{
    qDebug() << "battery state:" << state;
    m_notification->batteryStateMsgNotify(state);
}

void PowerManagerCenter::dealLowBatteryChanged(const int &state)
{
    qDebug() << "low battery state :" << state;
    switch (state) {
        case Low:
            m_notification->lowBatteryNotify();
            break;
        case Critical:
            m_lowBattery->veryLowBatteryDialog(m_config->getSysData().sysActionCriticalBat);
            break;
        default:
            m_lowBattery->veryLowBatteryControlStop();
            break;
    }
}

void PowerManagerCenter::dealLowBatteryControl()
{
    m_control->dealControlAction(m_config->getSysData().sysActionCriticalBat, true);
}

QString PowerManagerCenter::transformData(const QString &data)
{
    if ("shutdown" == data) {
        return POWER_OFF;
    } else if ("suspend" == data) {
        return SUSPEND;
    } else if ("blank" == data) {
        return TURN_OFF_DISPLAY;
    } else if ("hibernate" == data) {
        return HIBERNATE;
    } else {
        return NO_ACTION;
    }
}

void PowerManagerCenter::setIdleTime(const int &type)
{
    if (Laptop == type && m_onBattery) {
        m_idle->setIdleDisplayTime(m_config->getSysData().sysSleepDisplayBat);
        m_idle->setIdleSuspendTime(m_config->getSysData().sysSleepComputerBat);
    } else {
        m_idle->setIdleDisplayTime(m_config->getSysData().sysSleepDisplayAc);
        m_idle->setIdleSuspendTime(m_config->getSysData().sysSleepComputerAc);
    }
}

bool PowerManagerCenter::getOnBatteryState()
{
    QDBusInterface iface(UPOWER_SERVICE, UPOWER_PATH, UPOWER_INTERFACE, QDBusConnection::systemBus());
    return iface.property("OnBattery").toBool();
}
